/* Copyright (c) Colorado School of Mines, 2011.*/
/* All rights reserved.                       */

/*
 *  GENESIS  Copyright (c) 1986, 1990 by John J. Grefenstette
 *  This program may be freely copied for educational
 *  and research purposes.  All other rights reserved.
 *
 *  file:	input.c
 *
 *  purpose:	Set up filenames and read the input files, and
 *		initialize variables for this run.
 *
 *		See init.c for the initialization of variables for each
 *		experiment.
 *
 *  modified:	26 jun 86
 *		15 sep 90: read template file for floating point representation
 */

#include "extern.h"
#include "cwp.h"

extern void sranuni();

genesis_input(s)
char *s;
{
	FILE *fopen(), *fp;

	int i;			/* loop control				*/
	int seed;		/* my seed 				*/
	int members_exchanged;	/* used in memory allocatio of Exchange */
	char msg[80];		/* used when printing error message	*/
	char *cf;
	long clock;		/* current date				*/

	long time();
	char *ctime();
	int ilog2();

	/* set up file names */

	cf = malloc(1);
	*cf = 48 + instance;	/* this will identify files generated by */
				/* different processors			 */

        sprintf(Infile, "%s/in.%s", workdir, s);
	sprintf(Templatefile, "%s/template.%s", workdir, s);
        sprintf(FlowBestfile, "%s/best.%s.%s", workdir, s, cf);
        sprintf(Answerfile, "%s/answer.%s.%s", workdir, s, cf);

	/* read in the parameters from the infile */

	if ((fp = fopen(Infile, "r")) == NULL)
	{
		sprintf(msg, "Input: can't open %s", Infile);
		Error(msg);
	}
	fscanf(fp,IN_FORMAT,IN_VARS);
	Seed = OrigSeed;
	fclose(fp);

	Seed = Seed + 5000 * instance;	/* Just to vary */
	seed = Seed;
	sranuni(seed);

	if (verbose)
	{
        	fprintf(stderr,"Report from subpopulation %d among %d subpopulations\n",instance, Ncities);
        	fprintf(stderr,"Subpopulation %d has size %d\n",instance,Popsize);
        	fprintf(stderr,"Subpopulation %d has %d source statics\n",instance, NSOURCES);
        	fprintf(stderr,"Subpopulation %d has %d receiver statics\n",instance, NRECEIVERS);
        	fprintf(stderr,"Subpopulation %d has %d CMPS\n",instance, NCMP);
        	fprintf(stderr,"Subpopulation %d has receiver spacing %f\n",instance, dx);
		fprintf(stderr,"Subpopulation %d has maximum lag %d\n", instance, TOTAL_LAG);
        	fprintf(stderr,"Subpopulation %d will perform %d evolutions\n",instance,Numevolutions);
        	fprintf(stderr,"Subpopulation %d will iterate %d times per evolution\n",instance,Totaltrials);
		if (smooth)
			fprintf(stderr,"Receiver statics will be smoothed\n");

		if (uphill)
		{
			fprintf(stderr,"Subpopulation %d will perform uphill begining at evolution %d\n",instance, Min_evol_cg);
			fprintf(stderr,"Subpopulation %d will limit uphill to %d iterations\n",instance,max_iter);
        		sprintf(Options, "iRFcfgemU");
		}
		else
		{
			fprintf(stderr,"Subpopulation %d will not perform uphill\n", instance);
        		sprintf(Options, "iRFcfgem");
		}

		fprintf(stderr,"Subpopulation %d has crossover probability %f\n", instance, C_rate);
		fprintf(stderr,"Subpopulation %d has mutation probability %f\n",instance, M_rate);
        	fprintf(stderr,"Subpopulation %d has random seed %d\n",instance,Seed);
		fprintf(stderr,"Subpopulation %d has working directory %s\n", instance, workdir);
		fprintf(stderr,"Subpopulation %d has data file name %s\n", instance, datafile);
		fprintf(stderr,"Subpopulation %d has Xcorrelation file name %s\n", instance, Xcorrfile);
	}
	else
	{
                if (uphill)
                        sprintf(Options, "iRFcfgemU");
                else
                        sprintf(Options, "iRFcfgem");
	}

	/* activate the Options */
 	for (i=0; Options[i] != '\0'; i++)
		Setflag(Options[i]);
	if (Displayflag)
		Traceflag = 0;

	/* Bytes is the size of each packed chromosome */
	Bytes = Length / CHARSIZE;
	if (Length % CHARSIZE) Bytes++;

	/* read template file if used */
	if (Floatflag)
	{
		if ((fp = fopen(Templatefile, "r")) == NULL)
		{
			sprintf(msg, "Template: can't open %s", Templatefile);
			Error(msg);
		}
		fscanf(fp, "genes: %d ", &Genes);
		Gene = (GENESTRUCT *) calloc((unsigned) Genes,
			sizeof(GENESTRUCT));
			
		for (i=0; i<Genes; i++)
		{
			fscanf(fp, " gene %*d");
			fscanf(fp, " min: %lf", &Gene[i].min);
			fscanf(fp, " max: %lf", &Gene[i].max);
			fscanf(fp, " values: %lu", &Gene[i].values);
			fscanf(fp, " format: %s", Gene[i].format);
			Gene[i].bitlength = ilog2(Gene[i].values);
			Gene[i].incr = (Gene[i].max - Gene[i].min) / 
						(Gene[i].values - 1);
		}
		fclose(fp);
	}
	/* allocate storage for variable sized structures */

	/* used for floating representation of chromosomes */
	Vector = (double *) calloc((unsigned) Genes, sizeof(double));

	/* used for string representation of chromosomes */
	Bitstring = malloc((unsigned) (Length+1));
	Bitstring[Length] = '\0';

	/* used for DEBUGGING */
	DebugBuff = malloc((unsigned) (Length+1));
	DebugBuff[Length] = '\0';

	if (Bitstring == NULL) {
		printf("input: Help!  Memory allocation failed for Bitstring\n");
		abort();
	}
	/* population arrays */
	Old = (STRUCTURE *) calloc((unsigned) Popsize, sizeof(STRUCTURE));
	New = (STRUCTURE *) calloc((unsigned) Popsize, sizeof(STRUCTURE));
/*
    The Exchange array will be used for exchange purposes later
*/
        members_exchanged = NINT(Popsize * .1);
        Exchange = (STRUCTURE *) calloc((unsigned) members_exchanged, sizeof(STRUCTURE));

	for (i=0; i<Popsize; i++)
	{
		Old[i].Gene = malloc((unsigned) Bytes);
		New[i].Gene = malloc((unsigned) Bytes);
	}
/*
        Allocating auxiliary quantities
*/
        indx_exchange = alloc1int((unsigned) members_exchanged + 1);
        indx_new = alloc1int((unsigned) Popsize + 1);
        performance = alloc1double((unsigned) Popsize + 1);

	if (indx_exchange == NULL || indx_new == NULL || performance == NULL) {
		fprintf(stderr,"input: Help!  Memory allocation failed for auxiliary sorting variables\n");
		abort();
	}

        for (i=0; i<members_exchanged; i++)
        {
                Exchange[i].Gene = malloc((unsigned) Bytes);
        }
/*
    	Next variables will be used to help the efficiency of the GA 
 	regarding reading the Xcorrelation file
*/
	to_be_calculated = alloc2double((unsigned) Genes, (unsigned) Popsize);
	if (to_be_calculated == NULL)
		Error("input: Problems with memory allocation for to_be_calculated");
	eval_returned = alloc1double((unsigned) Popsize);
	if (eval_returned == NULL)
		Error("input: Problems with memory allocation for eval_returned");
/*
    	Variables for_conjg and Perf_past will be used in the conjugate 
	gradient procedure
*/
	for_conjg = alloc2double((unsigned) Genes, (unsigned) Popsize);
	if (for_conjg == NULL)
		Error("input: Problems with memory allocation for for_conjg");

        Perf_past = alloc1double((unsigned) Popsize);
        if (Perf_past == NULL)
                Error("input: Problems with memory allocation for Perf_past");

	/* used to compute moving value for Worst */
	if (Windowsize)
	Window = (double *) calloc((unsigned) Windowsize, sizeof(double));
    
	/* Probably a good point to open the Xcorrelation file */

        Xfp = fopen(Xcorrfile,"r");
        if (Xfp == NULL)
        {
                sprintf(msg, "Input: can't open Xcorrfile %s", Xcorrfile);
                Error(msg);
        }

	/* used to save best structures */
	if (Savesize)
	 Bestset = (BESTSTRUCT *) calloc((unsigned) Savesize, sizeof(BESTSTRUCT));

	for (i=0; i<Savesize; i++)
		Bestset[i].Gene = malloc((unsigned) Bytes);
	
	/* echo Input params */
	if (Traceflag) printf(OUT_FORMAT, OUT_VARS);

	/* scratch the output file (unless this is a restart) */
	if (!Restartflag)
	{
                if ((fp = fopen(FlowBestfile, "w")) == NULL)
                {
                        sprintf(msg, "Input: can't open %s", FlowBestfile);
                        Error(msg);
                }
                fclose(fp);

                if ((fp = fopen(Answerfile, "w")) == NULL)
                {
                        sprintf(msg, "Input: can't open %s", Answerfile);
                        Error(msg);
                }
	}
}


int ilog2(n)
	unsigned long n;
{
	register int i;

	if (n <= 0)
	{
		printf("Help! values is %d, must be positive!\n", n);
		abort();
	}
	
	i = 0;
	while ((int) (n & 1) == 0)
	{
		n >>= 1;
		i++;
	}
	return(i);
}


Setflag(c)
char c;
{
	switch (c) {
	case 'a' :
		Allflag = 1;
		break;
	case 'b' : 
		Bestflag = 1; 
		break;
	case 'c' : 
		Collectflag = 1; 
		Convflag = 1;
		break;
	case 'C' : 
		Collectflag = 1; 
		break;
	case 'd' : 
		Dumpflag = 1; 
		break;
	case 'D' : 
		Displayflag = 1; 
		break;
	case 'e' :
		Eliteflag = 1;
		break;
	case 'f' : 
		Floatflag = 1; 
		break;
	case 'g' :
		Grayflag = 1;
		break;
	case 'i' :
		Initflag = 1;
		break;
	case 'I' :
		Interflag = 1;
		Displayflag = 1;
		break;
	case 'l' :
		Logflag = 1;
		break;
	case 'L' :
		Lastflag = 1;
		break;
	case 'M' :
		Maxflag = 1;
		break;
	case 'o' : 
		Onlnflag = 1; 
		break;
	case 'O' :
		Offlnflag = 1;
		break;
	case 'r' : 
		Restartflag = 1; 
		break;
	case 'R' : 
		Rankflag = 1; 
		break;
	case 's' : 
		Schemflag = 1; 
		break;
	case 't' : 
		Traceflag = 1; 
		break;
        case 'F' :
                FlowBestflag = 1;
                break;
        case 'A' :
                RandomSent = 1;
                break;
        case 'U' :
                Uphillflag = 1;
                break;
        case 'm' :
                StepMutflag = 1;
                break;
	case 'B' :
		DownHillflag = 1;
		break;
	}
}
/** end of file **/
